
// 实现MyPromise
const PENDING = 'pending'
// 成功
const FULFILLED = 'fulfilled'
// 失败
const REJECTED = 'rejected'
class MyPromise {
    // 初始化状态
    status = PENDING
    // 存储执行结果
    value = undefined
    reason = undefined
    // 成功回调，兼容多个then调用
    onSuccessCallback = []
    // 失败回调，兼容多个then调用
    onFailedCallback = []
    // 修改状态为成功
    resolve = (value) => {
        // 如果当前promise的状态不是pending，那么不允许修改状态
        if (this.status !== PENDING) return
        this.status = FULFILLED
        this.value = value
        // 依次执行
        while (this.onSuccessCallback.length) this.onSuccessCallback.shift()(value)
    }
    // 修改状态为失败
    reject = (reason) => {
        // 如果当前promise的状态不是pending，那么不允许修改状态
        if (this.status !== PENDING) return
        this.status = REJECTED
        this.reason = reason
        while (this.onFailedCallback.length) this.onFailedCallback.shift()(reason)
    }
    // 实现 new Promise((resolve, reject) => {})
    constructor(excutor) {
        // 立即执行，传入resolve, reject
        try {
            excutor(this.resolve, this.reject)
        }
        catch (e) {
            // 捕获执行异常
            this.reject(e)
        }
    }

    // 模拟then方法
    then(onSuccessCallback, onFailedCallback) {
        // 添加默认赋值
        onSuccessCallback = onSuccessCallback || (value => value)
        onFailedCallback = onFailedCallback || (err => err)
        // 由于then方法返回MyPromise对象实现链式调用，所以在这里实例化MyPromise
        let promise = new MyPromise((resolve, reject) => {
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        let value = onSuccessCallback(this.value)
                        // 通过异步调用，可以获取promise对象
                        resolvePormise(promise, value, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                }, 0)

            } else if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        let value = onFailedCallback(this.reason)
                        // 通过异步调用，可以获取promise对象
                        resolvePormise(promise, value, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                }, 0)
            }
            // 异步调用时，此时状态尚处于pending，因此需要缓存成功失败执行方法，当状态发生改变的时候，再执行 
            else {
                this.onSuccessCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let value = onSuccessCallback(this.value)
                            // 通过异步调用，可以获取promise对象
                            resolvePormise(promise, value, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                })
                this.onFailedCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let value = onFailedCallback(this.reason)
                            // 通过异步调用，可以获取promise对象
                            resolvePormise(promise, value, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                })
            }
        })
        return promise
    }

    catch(reject) {
        this.then(undefined, reject)
    }

    static resolve(value) {
        if (value instanceof MyPromise) {
            return value
        }
        return new MyPromise((resolve, reject) => {
            resolve(value)
        })
    }

    static reject(reason) {
        if (reason instanceof MyPromise) {
            return reason
        }
        return new MyPromise((resolve, reject) => {
            reject(reason)
        })
    }

    // 模拟all方法
    static all(array) {
        let result = []
        // 添加计数器，判断是否完成所有任务
        let index = 0
        function addData(i, value, resolve) {
            result[i] = value
            index += 1
            if (index === array.length) {
                resolve(result)
            }
        }
        return new MyPromise((resolve, reject) => {
            for (let i = 0; i < array.length; i++) {
                let current = array[i]
                // 判断传入的是否是MyPromise对象
                if (current instanceof MyPromise) {
                    current.then(value => addData(i, value, resolve), reason => reject(reason))
                } else {
                    addData(i, current, resolve)
                }
            }
        })


    }

    // 模拟race方法
    static race(array) {
        // 添加只执行一次的变量
        let stop = false
        return new MyPromise((resolve, reject) => {
            for (let i = 0; i < array.length; i++) {
                let current = array[i]
                // 判断传入的是否是MyPromise对象
                if (current instanceof MyPromise) {
                    current.then(value => {
                        // 如果没有执行过，那么执行resolve
                        if (!stop) {
                            stop = true
                            resolve(value)
                        }
                    }, reason => {
                        if (!stop) {
                            stop = true
                            reject(reason)
                        }
                    })
                } else {
                    if (!stop) {
                        stop = true
                        resolve(current)
                    }
                }
            }
        })
    }
}
// 提取公用的处理方法
function resolvePormise(promise, value, resolve, reject) {
    // 阻止链式调用
    if (promise === value) return reject(new TypeError('channing cycle'))
    // 判断value是否是MyPromise对象的一个实例
    if (value instanceof MyPromise) {
        // 如果是实例，name继续调用实例的then方法
        value.then(resolve, reject)
    } else {
        resolve(value)
    }
}

module.exports = MyPromise